package com.campus.counseling.controller;

import com.campus.counseling.model.common.Result;
import com.campus.counseling.entity.SysLoginLog;
import com.campus.counseling.entity.SysLoginStats;
import com.campus.counseling.model.mapper.SysLoginLogMapper;
import com.campus.counseling.model.mapper.SysLoginStatsMapper;
import com.campus.counseling.util.HttpClient;
import com.campus.counseling.util.UserAgentAnalyzer;
import eu.bitwalker.useragentutils.UserAgent;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSON;
import java.util.Map;
import java.time.temporal.ChronoUnit;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import java.util.List;

@Slf4j
@Tag(name = "登录日志")
@RestController
@RequestMapping("/api/system/login")
@RequiredArgsConstructor
public class LoginLogController {

    private final SysLoginLogMapper loginLogMapper;
    private final SysLoginStatsMapper loginStatsMapper;
    private final UserAgentAnalyzer userAgentAnalyzer;

    @PostMapping("/log")
    @Operation(summary = "记录登录日志")
    public Result<Void> recordLoginLog(@RequestBody SysLoginLog loginLog, HttpServletRequest request) {
        try {
            // 获取IP地址
            String ipAddress = getIpAddress(request);
            loginLog.setIp(ipAddress);
            
            // 解析User-Agent信息
            String userAgentString = loginLog.getUserAgent();
            UserAgent agent = userAgentAnalyzer.parseUserAgent(userAgentString);
            
            // 设置浏览器和操作系统信息
            loginLog.setBrowser(userAgentAnalyzer.getBrowserInfo(agent));
            loginLog.setOs(userAgentAnalyzer.getOperatingSystem(agent));
            loginLog.setDeviceType(userAgentAnalyzer.getDeviceType(agent));
            
            // 获取地理位置信息
            try {
                // 检查是否为本地IP地址
                if (isLocalIpAddress(ipAddress)) {
                    loginLog.setLocation("本地开发环境");
                } else {
                    String url = "http://whois.pconline.com.cn/ipJson.jsp?ip=" + ipAddress + "&json=true";
                    String response = HttpClient.get(url);
                    JSONObject json = JSON.parseObject(response);
                    String location = json.getString("pro") + " " + json.getString("city");
                    loginLog.setLocation(location);
                }
            } catch (Exception e) {
                log.warn("获取地理位置信息失败: {}", e.getMessage());
                loginLog.setLocation("未知");
            }
            
            // 设置创建时间
            LocalDateTime now = LocalDateTime.now();
            loginLog.setCreateTime(now);
            loginLog.setLoginDuration(0);
            
            // 保存登录日志
            loginLogMapper.insert(loginLog);
            
            // 更新统计数据
            updateLoginStats(loginLog, now);
            
            log.info("记录登录日志成功: userId={}, username={}, ip={}, location={}", 
                    loginLog.getUserId(), loginLog.getUsername(), ipAddress, loginLog.getLocation());
            
            return Result.success();
        } catch (Exception e) {
            log.error("记录登录日志失败: {}", e.getMessage(), e);
            return Result.error("记录登录日志失败");
        }
    }
    
    @PostMapping("/logout")
    @Operation(summary = "记录退出时间")
    public Result<Void> recordLogout(@RequestBody Map<String, Long> params) {
        try {
            Long userId = params.get("userId");
            if (userId == null) {
                return Result.error("用户ID不能为空");
            }

            // 查找最近的未退出登录记录
            SysLoginLog lastLog = loginLogMapper.selectOne(
                new LambdaQueryWrapper<SysLoginLog>()
                    .eq(SysLoginLog::getUserId, userId)
                    .isNull(SysLoginLog::getLogoutTime)  // 退出时间为空
                    .orderByDesc(SysLoginLog::getCreateTime)
                    .last("LIMIT 1")
            );

            if (lastLog != null) {
                LocalDateTime now = LocalDateTime.now();
                // 计算登录时长（秒）
                long duration = ChronoUnit.SECONDS.between(lastLog.getCreateTime(), now);

                // 更新登录时长和退出时间
                boolean updated = loginLogMapper.update(null,
                    new LambdaUpdateWrapper<SysLoginLog>()
                        .eq(SysLoginLog::getId, lastLog.getId())
                        .set(SysLoginLog::getLogoutTime, now)
                        .set(SysLoginLog::getLoginDuration, (int) duration)  // 使用loginDuration字段
                ) > 0;

                if (updated) {
                    log.info("记录退出时间成功: userId={}, duration={}s, logId={}", userId, duration, lastLog.getId());
                } else {
                    log.warn("更新登录记录失败: userId={}, logId={}", userId, lastLog.getId());
                }
            } else {
                log.warn("未找到需要更新的登录记录: userId={}", userId);
            }

            return Result.success();
        } catch (Exception e) {
            log.error("记录退出时间失败: {}", e.getMessage(), e);
            return Result.error("记录退出时间失败");
        }
    }
    
    @GetMapping("/log")
    @Operation(summary = "获取登录日志列表")
    public Result<List<SysLoginLog>> getLoginLogs() {
        try {
            // 查询最近的登录日志，按时间倒序排列
            List<SysLoginLog> logs = loginLogMapper.selectList(
                new LambdaQueryWrapper<SysLoginLog>()
                    .orderByDesc(SysLoginLog::getCreateTime)
                    .last("LIMIT 50")  // 限制返回最近50条记录
            );
            return Result.success(logs);
        } catch (Exception e) {
            log.error("获取登录日志失败: {}", e.getMessage(), e);
            return Result.error("获取登录日志失败");
        }
    }
    
    /**
     * 获取IP地址
     */
    private String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 如果是多级代理，取第一个IP
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        return ip;
    }

    /**
     * 检查是否为本地IP地址
     */
    private boolean isLocalIpAddress(String ip) {
        return ip == null 
            || ip.startsWith("127.") 
            || ip.equals("0:0:0:0:0:0:0:1") 
            || ip.equals("localhost")
            || ip.equals("::1")
            || ip.startsWith("192.168.")
            || ip.startsWith("10.")
            || ip.startsWith("172.16.")
            || ip.startsWith("172.17.")
            || ip.startsWith("172.18.")
            || ip.startsWith("172.19.")
            || ip.startsWith("172.20.")
            || ip.startsWith("172.21.")
            || ip.startsWith("172.22.")
            || ip.startsWith("172.23.")
            || ip.startsWith("172.24.")
            || ip.startsWith("172.25.")
            || ip.startsWith("172.26.")
            || ip.startsWith("172.27.")
            || ip.startsWith("172.28.")
            || ip.startsWith("172.29.")
            || ip.startsWith("172.30.")
            || ip.startsWith("172.31.");
    }

    /**
     * 更新登录统计数据
     */
    private void updateLoginStats(SysLoginLog loginLog, LocalDateTime now) {
        try {
            // 获取当前小时的统计记录
            LocalDateTime hourStart = now.withMinute(0).withSecond(0).withNano(0);
            SysLoginStats stats = loginStatsMapper.selectOne(
                new LambdaQueryWrapper<SysLoginStats>()
                    .eq(SysLoginStats::getStatDate, hourStart)
            );
            
            if (stats == null) {
                // 创建新的统计记录
                stats = new SysLoginStats();
                stats.setStatDate(hourStart);
                stats.setLoginCount(1);
                stats.setUniqueUserCount(1);
                stats.setSuccessCount(loginLog.getStatus() == 0 ? 1 : 0);
                stats.setFailCount(loginLog.getStatus() != 0 ? 1 : 0);
                stats.setAvgDuration(0);
                stats.setPeakHour(hourStart.getHour());
                stats.setCreateTime(now);
                stats.setUpdateTime(now);
                loginStatsMapper.insert(stats);
            } else {
                // 更新现有统计记录
                LambdaUpdateWrapper<SysLoginStats> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(SysLoginStats::getId, stats.getId())
                    .setSql("login_count = login_count + 1")
                    .setSql(loginLog.getStatus() == 0 ? 
                        "success_count = success_count + 1" : 
                        "fail_count = fail_count + 1");
                
                // 检查是否需要更新独立用户数
                Long userCount = loginLogMapper.selectCount(
                    new LambdaQueryWrapper<SysLoginLog>()
                        .eq(SysLoginLog::getUserId, loginLog.getUserId())
                        .between(SysLoginLog::getCreateTime, hourStart, hourStart.plusHours(1))
                );
                if (userCount == 1) {
                    updateWrapper.setSql("unique_user_count = unique_user_count + 1");
                }
                
                updateWrapper.set(SysLoginStats::getUpdateTime, now);
                loginStatsMapper.update(null, updateWrapper);
            }
        } catch (Exception e) {
            log.error("更新登录统计数据失败: {}", e.getMessage(), e);
            // 不抛出异常，避免影响主流程
        }
    }
} 